package com.firstsource.networking.ip.tracker.util;

public class IPManipulator {
	
	public static String ip2Binary (String ipAddr) {
		String[] octets = ipAddr.split("\\.") ;
		int a = Integer.parseInt(octets[0]) ;
		int b = Integer.parseInt(octets[1]) ;
		int c = Integer.parseInt(octets[2]) ;
		int d = Integer.parseInt(octets[3]) ;

		StringBuffer binAddr = new StringBuffer() ;
		String aa = Integer.toBinaryString(a) ;
		String bb = Integer.toBinaryString(b) ;
		String cc = Integer.toBinaryString(c) ;
		String dd = Integer.toBinaryString(d) ;
		
		int holder = 8 - aa.length() ;
		for (int x=0;x<holder;x++) {
			binAddr.append("0") ;
		}
		binAddr.append(aa) ;

		holder = 8 - bb.length() ;
		for (int x=0;x<holder;x++) {
			binAddr.append("0") ;
		}
		binAddr.append(bb) ;

		holder = 8 - cc.length() ;
		for (int x=0;x<holder;x++) {
			binAddr.append("0") ;
		}
		binAddr.append(cc) ;

		holder = 8 - dd.length() ;
		for (int x=0;x<holder;x++) {
			binAddr.append("0") ;
		}
		binAddr.append(dd) ;

		return binAddr.toString() ;
	}
	
	public static long binary2Long (String binary) {
		long longIP = Long.valueOf(binary, 2) ;
		
		return longIP ;
	}

	public static long ip2Long (String ipAddr) {
		return IPManipulator.binary2Long(IPManipulator.ip2Binary(ipAddr)) ;
	}

	public static String long2IP (long addr) {
		String binaryAddr = Long.toBinaryString(addr) ;
		StringBuffer padded = new StringBuffer() ;
		int length = binaryAddr.length() ;
		for (int x=0;x<(32-length);x++) {
			padded.append("0") ;
		}
		padded.append(binaryAddr) ;
		String a = padded.toString().substring(0,8) ;
		String b = padded.toString().substring(8,16) ;
		String c = padded.toString().substring(16,24) ;
		String d = padded.toString().substring(24,32) ;
		String decDotted = Integer.parseInt(a, 2)+"."+Integer.parseInt(b, 2)+"."+Integer.parseInt(c, 2)+"."+Integer.parseInt(d, 2) ;
		return decDotted ;
	}

	public static String netFromIP (String ipAddr, String netMask) {
		String binaryMask = IPManipulator.ip2Binary(netMask) ;
		String binaryAddr = IPManipulator.ip2Binary(ipAddr) ;
		StringBuffer netAddr = new StringBuffer() ;
		for (int x=0;x<32;x++) {
			if (binaryMask.charAt(x)=='1') {
				netAddr.append(binaryAddr.charAt(x)) ;
			} else {
				netAddr.append('0') ;
			}
		}
		return IPManipulator.long2IP(IPManipulator.binary2Long(netAddr.toString())) ;
	}

	public static long usableAddresses(String netMask) {
		long maskVal = IPManipulator.ip2Long(netMask) ;
		long fullMask = IPManipulator.ip2Long("255.255.255.255") ;
		long netLength = fullMask - maskVal - 2 ;

		return netLength ;
	}

	public static String firstAddr(String netAddr, String netMask) {
		long decMask = IPManipulator.ip2Long(netMask) ;
		long fullMask = IPManipulator.ip2Long("255.255.255.255") ;
		String retVal = null ;
		if (decMask<(fullMask-2)) {
			long decAddr = IPManipulator.ip2Long(netAddr) ;
			long first = decAddr + 1 ;
			retVal = IPManipulator.long2IP(first) ;
		} else {
			retVal = new String("ERROR") ;
		}

		return retVal ;
	}

	public static String lastAddr(String netAddr, String netMask) {
		long decMask = IPManipulator.ip2Long(netMask) ;
		long fullMask = IPManipulator.ip2Long("255.255.255.255") ;
		String retVal = null ;
		if (decMask<(fullMask-2)) {
			long decAddr = IPManipulator.ip2Long(netAddr) ;
			long last = decAddr + (fullMask-decMask-1) ;
			retVal = IPManipulator.long2IP(last) ;
		} else {
			retVal = new String("ERROR") ;
		}

		return retVal ;
	}

	public static String bcastAddr(String netAddr, String netMask) {
		long decMask = IPManipulator.ip2Long(netMask) ;
		long fullMask = IPManipulator.ip2Long("255.255.255.255") ;
		String retVal = null ;
		if (decMask<(fullMask-2)) {
			long decAddr = IPManipulator.ip2Long(netAddr) ;
			long bcast = decAddr + (fullMask-decMask) ;
			retVal = IPManipulator.long2IP(bcast) ;
		} else {
			retVal = new String("ERROR") ;
		}

		return retVal ;
	}
}
